﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using Pasta.Medio.Concrete;

namespace Pasta.Medio.Configuration
{
	public class AppSettings
	{
		#region Setting Properties                - - - - - - - - - - - - - - - - - - - - - - - - -

		// -- Image Folder
		public string ImageFolder { get; set; }

		// -- Video Folder
		public string VideoFolder { get; set; }

		// -- Incoming Images Folder
		public string IncomingImages
		{
			get { return Path.Combine(ImageFolder, "Incoming"); }
		}

		// -- Incoming Videos Folder
		public string IncomingVideos
		{
			get { return Path.Combine(VideoFolder, "Incoming"); }
		}

		// -- Photo Types
		public List<String> ImageTypes { get; set; }
		public String ImageTypesString
		{
			get { return String.Join(";", ImageTypes).Replace("*.", ""); }
		}

		// -- Video Types
		public List<String> VideoTypes { get; set; }
		public String VideoTypesString
		{
			get { return String.Join(";", VideoTypes).Replace("*.", ""); }
		}

		// -- Media Types
		public List<String> MediaTypes
		{
			get 
			{
				List<String> types = new List<string>(ImageTypes);
				types.AddRange(VideoTypes);
				return types;
			}
		}

		public String MediaTypesString
		{
			get { return String.Join(";", MediaTypes).Replace(".", ""); }
		}

		// -- Rename Pattern
		public String RenamePattern { get; set; }

		// -- Duplicate Pattern
		public String DuplicatePattern { get; set; }

		public bool HasErrors
		{
			get { return false; }
		}

		#endregion

		// local variables
		private Config _config;
		public Results Results { get; private set; }
		private bool _saveOnRead = false;

		/// <summary>
		/// Create Preferences for the company application. Collect errors and exceptions.
		/// </summary>
		/// <param name="company"></param>
		/// <param name="application"></param>
		/// <param name="errors"></param>
		/// 
		/// 
		public AppSettings(string company, string application)
		{
			Results = new Results();
			_config = new Config(company, application);
			if (_config == null)
			{
				Results.AddError("Unable to read the user settings for Medio");
			}
			_saveOnRead = !_config.HasFile;

			ImageFolder = ReadSetting(Constants.ImageFolder, Defaults.ImageFolder, Enums.SettingOptions.CheckFolder);
			VideoFolder = ReadSetting(Constants.VideoFolder, Defaults.VideoFolder, Enums.SettingOptions.CheckFolder);
			ImageTypes = ReadTypes(_config[Constants.ImageTypes], Defaults.PhotoTypes);
			VideoTypes = ReadTypes(_config[Constants.VideoTypes], Defaults.VideoTypes);
			RenamePattern = ReadSetting(Constants.RenamePattern, Defaults.RenamePattern);
			DuplicatePattern = ReadSetting(Constants.DuplicatePattern, Defaults.DuplicatePattern);
			//DuplicateAction = ReadSetting("DuplicateAction", DefaultDuplicateAction);

			CreateFolder(IncomingImages);
			CreateFolder(IncomingVideos);

			if( !HasErrors && _saveOnRead )
			{
				Save();
			}
		}

		private string ReadSetting(string key, string defaultValue, Enums.SettingOptions options = Enums.SettingOptions.Normal)
		{
			try
			{
				string setting = _config[key].Trim();
				if (String.IsNullOrEmpty(setting))
				{
					setting = defaultValue;
					_saveOnRead = true;
				}
				if ((options & Enums.SettingOptions.CheckFolder) != 0)
				{
					if (!Directory.Exists(setting))
					{
						Results.AddError("Folder {0} cannot be found", setting);
						setting = null;
					}
				}
				else if ((options & Enums.SettingOptions.CreateFolder) != 0)
				{
					if (!CreateFolder(setting))
					{
						setting = null;
					}
				}
				return setting;
			}
			catch (Exception ex)
			{
				Results.AddError("Error reading setting {0}:\n  {1}", key, ex.Message);
			}
			return null;
		}

		private bool CreateFolder(string folder)
		{
			if (!Directory.Exists(folder))
			{
				try
				{
					Directory.CreateDirectory(folder);
				}
				catch (ArgumentNullException)
				{
					Results.AddError("Cannot create a folder with an empty name");
				}
				catch (ArgumentException)
				{
					Results.AddError("Invalid folder name {0}", folder);
				}
				catch (UnauthorizedAccessException)
				{
					Results.AddError("You don't have permissions to create folder {0}", folder);
				}
				catch
				{
					Results.AddError("Unable to create folder {0}", folder);
				}
			}
			return Results.Success;
		}

		public static List<string> ReadTypes(string types, string def = "")
		{
			string[] list = types.Split(Constants.TypeSeparators, StringSplitOptions.RemoveEmptyEntries);
			if (list.Count() == 0)
			{
				list = def.Split(';');
			}
			return list.Select(s => "*." + s).ToList();
		}

		public void Save()
		{
			try
			{
				_config[Constants.ImageFolder] = ImageFolder;
				_config[Constants.VideoFolder] = VideoFolder;
				_config[Constants.ImageTypes] = ImageTypesString;
				_config[Constants.VideoTypes] = VideoTypesString;
				_config[Constants.RenamePattern] = RenamePattern;
				_config[Constants.DuplicatePattern] = DuplicatePattern;
				_config.Save();
			}
			catch
			{
				Results.AddError("Unable to save configuration to {0}", _config.FilePath);
			}
		}
	}
}
